package com.huohuzhihui.api.service.impl;

import com.alibaba.fastjson.JSON;
import com.huohuzhihui.account.domain.AccUserAccount;
import com.huohuzhihui.api.service.ApiAccountService;
import com.huohuzhihui.api.service.ApiPayService;
import com.huohuzhihui.common.core.domain.entity.SysUser;
import com.huohuzhihui.common.exception.CustomException;
import com.huohuzhihui.common.utils.DateUtils;
import com.huohuzhihui.common.utils.uuid.IdUtils;
import com.huohuzhihui.knowledge.domain.KnowleageCourse;
import com.huohuzhihui.knowledge.mapper.KnowleageCourseMapper;
import com.huohuzhihui.system.service.ISysConfigService;
import com.huohuzhihui.trade.domain.AccTradeRecord;
import com.huohuzhihui.trade.domain.TradeOrder;
import com.huohuzhihui.trade.mapper.AccTradeRecordMapper;
import com.huohuzhihui.trade.mapper.TradeOrderMapper;
import com.huohuzhihui.trade.service.ITradeOrderService;
import com.ijpay.core.enums.SignType;
import com.ijpay.core.enums.TradeType;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.WxPayApiConfig;
import com.ijpay.wxpay.model.OrderQueryModel;
import com.ijpay.wxpay.model.UnifiedOrderModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * 订单Service业务层处理
 * 
 * @author huohuzhihui
 * @date 2020-11-15
 */
@Service
public class ApiPayServiceImpl implements ApiPayService {
    @Autowired
    private TradeOrderMapper tradeOrderMapper;
    @Autowired
    private ISysConfigService sysConfigService;
    @Autowired
    private ITradeOrderService iTradeOrderService;
    @Autowired
    private AccTradeRecordMapper accTradeRecordMapper;
    @Autowired
    private KnowleageCourseMapper knowleageCourseMapper;
    @Autowired
    private ApiAccountService apiAccountService;

    @Value("${wxpay.appId}")
    private String appId;

    @Value("${wxpay.appSecret}")
    private String appSecret;

    @Value("${wxpay.certPath}")
    private String certPath;

    @Value("${wxpay.domain}")
    private String domain;

    @Value("${wxpay.mchId}")
    private String mchId;

    @Value("${wxpay.partnerKey}")
    private String partnerKey;

    @Value("${wxpay.notifyUrl}")
    private String notifyUrl;

    @Value("${wxpay.refundNotifyUrl}")
    private String refundNotifyUrl;

    private WxPayApiConfig wxPayApiConfig;

    @PostConstruct
    public WxPayApiConfig getApiConfig() {
        wxPayApiConfig = WxPayApiConfig.builder()
                .appId(appId)
                .mchId(mchId)
                .partnerKey(partnerKey)
                .certPath(certPath)
                .domain(domain)
                .build();
        return wxPayApiConfig;
    }

    @Override
    public String addOrder(SysUser sysUser , BigDecimal amount, String source, String channelCode, String openId, String ip,Long courseId) {
        if(sysUser != null) {
            String type = "1";//充值
            String tradeNo = IdUtils.fastSimpleUUID();

            iTradeOrderService.insertTradeOrder(type, sysUser.getUserId(), sysUser.getUserName(), amount, source, courseId, channelCode, sysUser.getUserName(),tradeNo);

            KnowleageCourse knowleageCourse = knowleageCourseMapper.selectKnowleageCourseById(courseId);
            String subject = knowleageCourse.getCourseName();
            String body = knowleageCourse.getCourseDescription();

            Map<String, String> params = UnifiedOrderModel
                    .builder()
                    .appid(wxPayApiConfig.getAppId())
                    .mch_id(wxPayApiConfig.getMchId())
                    .nonce_str(WxPayKit.generateStr())
                    .body(body)
                    .attach(subject)
                    .out_trade_no(tradeNo)
                    .total_fee(amount.multiply(new BigDecimal("100")).stripTrailingZeros().toPlainString())
                    .spbill_create_ip(ip)
                    .notify_url(notifyUrl)
                    .trade_type(TradeType.JSAPI.getTradeType())
                    .openid(openId)
                    .build()
                    .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);

            String xmlResult = WxPayApi.pushOrder(false, params);

            Map<String, String> result = WxPayKit.xmlToMap(xmlResult);

            String returnCode = result.get("return_code");
            String returnMsg = result.get("return_msg");
            if (!WxPayKit.codeIsOk(returnCode)) {
                throw new CustomException(returnMsg,500);
            }
            String resultCode = result.get("result_code");
            if (!WxPayKit.codeIsOk(resultCode)) {
                throw new CustomException(returnMsg,500);
            }
            // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回
            String prepayId = result.get("prepay_id");
            Map<String, String> packageParams = WxPayKit.miniAppPrepayIdCreateSign(wxPayApiConfig.getAppId(), prepayId,
                    wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);
            packageParams.put("outTradeNo",tradeNo);
            String jsonStr = JSON.toJSONString(packageParams);
            System.out.println("支付结果------------------"+jsonStr);
            return jsonStr;
        }
        return null;
    }

    @Override
    public String webPay(Long userId, String amount, String source, String channelCode, String openId, String ip, Long courseId) {
        // openId，采用 网页授权获取 access_token API：SnsAccessTokenApi获取
        String type = "1";//充值
        String tradeNo = IdUtils.fastSimpleUUID();

        SysUser sysUser = apiAccountService.getUserById(userId);

        iTradeOrderService.insertTradeOrder(type, sysUser.getUserId(), sysUser.getUserName(), new BigDecimal(amount), source, courseId, channelCode, sysUser.getUserName(),tradeNo);

        KnowleageCourse knowleageCourse = knowleageCourseMapper.selectKnowleageCourseById(courseId);

        String subject = knowleageCourse.getCourseName();
        String body = knowleageCourse.getCourseDescription();


        Map<String, String> params = UnifiedOrderModel
                .builder()
                .appid(wxPayApiConfig.getAppId())
                .mch_id(wxPayApiConfig.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .body(body)
                .attach(subject)
                .out_trade_no(tradeNo)
                .total_fee(new BigDecimal(amount).multiply(new BigDecimal("100")).stripTrailingZeros().toPlainString())
                .spbill_create_ip(ip)
                .notify_url(notifyUrl)
                .trade_type(TradeType.JSAPI.getTradeType())
                .openid(openId)
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);

        String xmlResult = WxPayApi.pushOrder(false, params);

        Map<String, String> resultMap = WxPayKit.xmlToMap(xmlResult);
        String returnCode = resultMap.get("return_code");
        String returnMsg = resultMap.get("return_msg");
        if (!WxPayKit.codeIsOk(returnCode)) {
            throw new CustomException(returnMsg,500);
        }
        String resultCode = resultMap.get("result_code");
        if (!WxPayKit.codeIsOk(resultCode)) {
            throw new CustomException(returnMsg,500);
        }

        // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回

        String prepayId = resultMap.get("prepay_id");

        Map<String, String> packageParams = WxPayKit.prepayIdCreateSign(prepayId, wxPayApiConfig.getAppId(),
                wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);
        packageParams.put("outTradeNo",tradeNo);
        String jsonStr = JSON.toJSONString(packageParams);
        return jsonStr;
    }

    @Override
    public String queryOrder(String outTradeNo) {
        try {

            Map<String, String> params = OrderQueryModel.builder()
                    .appid(wxPayApiConfig.getAppId())
                    .mch_id(wxPayApiConfig.getMchId())
                    .out_trade_no(outTradeNo)
                    .nonce_str(WxPayKit.generateStr())
                    .build()
                    .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5);
            String xmlResult = WxPayApi.orderQuery(params);


            Map<String, String> resultMap = WxPayKit.xmlToMap(xmlResult);
            String returnCode = resultMap.get("return_code");
            String returnMsg = resultMap.get("return_msg");
            if (!WxPayKit.codeIsOk(returnCode)) {
                throw new CustomException(returnMsg,500);
            }
            String resultCode = resultMap.get("result_code");
            if (!WxPayKit.codeIsOk(resultCode)) {
                throw new CustomException(returnMsg,500);
            }

            //完成订单状态修改
            String tradeNo = resultMap.get("out_trade_no");
            String tradeState = resultMap.get("trade_state");
            // 更新订单信息
            AccTradeRecord accTradeRecord = this.accTradeRecordMapper.selectAccTradeRecordByTradeNo(tradeNo);
            if(accTradeRecord.getStatus()==2){
                if(WxPayKit.codeIsOk(tradeState)){//支付成功
                    accTradeRecord.setStatus(1);
                    accTradeRecord.setUpdateTime(DateUtils.getNowDate());
                    accTradeRecord.setUpdateBy("系统");
                    accTradeRecordMapper.updateAccTradeRecord(accTradeRecord);

                    //更新订单状态
                    long orderId = accTradeRecord.getTradeOrderId();
                    TradeOrder tradeOrder = this.tradeOrderMapper.selectTradeOrderById(orderId);
                    tradeOrder.setStatus(1);
                    tradeOrder.setUpdateTime(DateUtils.getNowDate());
                    tradeOrder.setUpdateBy("系统");
                    tradeOrderMapper.updateTradeOrder(tradeOrder);
                }else{//支付失败
                    accTradeRecord.setStatus(2);
                    accTradeRecord.setUpdateTime(DateUtils.getNowDate());
                    accTradeRecord.setUpdateBy("系统");
                    accTradeRecordMapper.updateAccTradeRecord(accTradeRecord);

                    //更新订单状态
                    long orderId = accTradeRecord.getTradeOrderId();
                    TradeOrder tradeOrder = this.tradeOrderMapper.selectTradeOrderById(orderId);
                    tradeOrder.setStatus(2);
                    tradeOrder.setUpdateTime(DateUtils.getNowDate());
                    tradeOrder.setUpdateBy("系统");
                    tradeOrderMapper.updateTradeOrder(tradeOrder);
                }

            }

            Map<String, String> result = new HashMap<String, String>();
            result.put("trade_state",resultMap.get("trade_state"));
            result.put("trade_state_desc",resultMap.get("trade_state_desc"));
            String jsonStr = JSON.toJSONString(result);
            return jsonStr;
        } catch (Exception e) {
            e.printStackTrace();
            return "系统错误";
        }
    }
}

